/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package digitaldreamers.libraries.games.servers.databasemanagement.concrete.mysql;

import java.io.InputStream;
import java.io.Reader;
import java.math.BigDecimal;
import java.net.URL;
import java.sql.Date;
import java.sql.*;
import java.util.*;

/**
 * This is an edited version from the original one found at: http://www.javaworld.com/javaworld/jw-04-2007/jw-04-jdbc.html?page=2
 * @author DaoLe
 */
class NamedParameterStatement implements CallableStatement {
    // <editor-fold defaultstate="collapsed" desc="Constants">
    
    // <editor-fold defaultstate="collapsed" desc="Error messages">
    private static String ERROR_MESSAGE__PARAMETER_NAME_NOT_FOUND = "Parameter not found: %s";
    // </editor-fold>
            
    private static final char PARAMETER_IDENTIFIER = '@';
    private static final char MYSQL_PARAMETER_SYMBOL = '?';
    // </editor-fold>
    
    // <editor-fold defaultstate="collapsed" desc="Members">
    private PreparedStatement mStatement;
    private HashMap mParameterIndexMap;
    // </editor-fold>
    
    // <editor-fold defaultstate="collapsed" desc="Getters/Setters">
    /**
     * Returns the underlying statement.
     * @return The statement.
     */
    public PreparedStatement getStatement() {
        return mStatement;
    }
    // </editor-fold>
    
    // <editor-fold defaultstate="collapsed" desc="Constructors">
    /**
     * Creates a NamedParameterStatement. Wraps a call to c.{@link Connection#prepareStatement(java.lang.String) prepareStatement}.
     *
     * @param pConnection The database pConnection.
     * @param pSqlStatement The parameterized query.
     * @throws SQLException If the statement could not be created.
     */
    public NamedParameterStatement(Connection pConnection, String pSqlStatement) throws SQLException {
        mParameterIndexMap = new HashMap();
        String parsedQuery = parse(pSqlStatement, mParameterIndexMap);
        mStatement = pConnection.prepareStatement(parsedQuery);
    }
    // </editor-fold>
    
    // <editor-fold defaultstate="collapsed" desc="Methods">
    
    // <editor-fold defaultstate="collapsed" desc="Static Methods">
    /**
     * Parses a query with named parameters.  The parameter-index mappings are put into the map, and the
     * parsed query is returned.  DO NOT CALL FROM CLIENT CODE.  This method is non-private so JUnit code can
     * test it.
     * @param pSqlStatement SQL statement to parse.
     * @param pParameterIndexMap Map to hold parameter-index mappings.
     * @return The parsed query.
     */
    private static String parse(String pSqlStatement, HashMap pParameterIndexMap) {
        int length = pSqlStatement.length();
        StringBuilder parsedSqlStatement = new StringBuilder(length);
        boolean isInSingleQuote = false;
        boolean isInDoubleQuote = false;
        int parameterIndex = 1;
        
        for (int i = 0; i < length; i++) {
            char c = pSqlStatement.charAt(i);
            if (isInSingleQuote) {
                if (c == '\'') {
                    isInSingleQuote = false;
                }
            } else if (isInDoubleQuote) {
                if (c == '"') {
                    isInDoubleQuote = false;
                }
            } else {
                if (c == '\'') {
                    isInSingleQuote = true;
                } else if (c == '"') {
                    isInDoubleQuote = true;
                } else if (c == PARAMETER_IDENTIFIER && i + 1 < length && Character.isJavaIdentifierStart(pSqlStatement.charAt(i + 1))) {
                    int j = i + 2;
                    while (j < length && Character.isJavaIdentifierPart(pSqlStatement.charAt(j))) {
                        j++;
                    }
                    String parameterName = pSqlStatement.substring(i + 1, j);
                    
                    // Replace the parameter with a question mark.
                    c = MYSQL_PARAMETER_SYMBOL;
                    
                    // Skip the characters that present the parameter name.
                    i += parameterName.length();

                    List indexList = (List) pParameterIndexMap.get(parameterName);
                    if (indexList == null) {
                        indexList = new LinkedList<Integer>();
                        pParameterIndexMap.put(parameterName, indexList);
                    }
                    indexList.add(parameterIndex);
                    
                    parameterIndex++;
                }
            }
            parsedSqlStatement.append(c);
        }
        
        // Replace the lists of Integer objects with arrays of ints
        for (Iterator itr = pParameterIndexMap.entrySet().iterator(); itr.hasNext();) {
            Map.Entry entry = (Map.Entry) itr.next();
            List list = (List) entry.getValue();
            int[] indexes = new int[list.size()];
            int i = 0;
            for (Iterator itr2 = list.iterator(); itr2.hasNext();) {
                Integer index = (Integer) itr2.next();
                indexes[i++] = index;
            }
            entry.setValue(indexes);
        }
        return parsedSqlStatement.toString();
    }
    
    /**
     * Returns the indexes for a parameter.
     *
     * @param pParameterName Parameter name.
     * @return Parameter indexes.
     * @throws IllegalArgumentException If the parameter does not exist.
     */
    private int[] getIndexes(String pParameterName) throws IllegalArgumentException {
        int[] indexes = (int[]) mParameterIndexMap.get(pParameterName);
        if (indexes == null) {
            throw new IllegalArgumentException(String.format(ERROR_MESSAGE__PARAMETER_NAME_NOT_FOUND, pParameterName));
        }
        return indexes;
    }
    
    // <editor-fold defaultstate="collapsed" desc="Wrapper methods for CallableStatement object's methods">
    
    @Override
    public ResultSet executeQuery(String pSqlStatement) throws SQLException {
        return mStatement.executeQuery(pSqlStatement);
    }
    
    @Override
    public int executeUpdate(String pSqlStatement) throws SQLException {
        return mStatement.executeUpdate(pSqlStatement);
    }
    
    @Override
    public void close() throws SQLException {
        mStatement.close();
    }
    
    @Override
    public int getMaxFieldSize() throws SQLException {
        return mStatement.getMaxFieldSize();
    }
    
    @Override
    public void setMaxFieldSize(int pMax) throws SQLException {
        mStatement.setMaxFieldSize(pMax);
    }
    
    @Override
    public int getMaxRows() throws SQLException {
        return mStatement.getMaxRows();
    }
    
    @Override
    public void setMaxRows(int pMax) throws SQLException {
        mStatement.setMaxRows(pMax);
    }
    
    @Override
    public void setEscapeProcessing(boolean pEnable) throws SQLException {
        mStatement.setEscapeProcessing(pEnable);
    }
    
    @Override
    public int getQueryTimeout() throws SQLException {
        return mStatement.getQueryTimeout();
    }
    
    @Override
    public void setQueryTimeout(int pSeconds) throws SQLException {
        mStatement.setQueryTimeout(pSeconds);
    }
    
    @Override
    public void cancel() throws SQLException {
        mStatement.cancel();
    }
    
    @Override
    public SQLWarning getWarnings() throws SQLException {
        return mStatement.getWarnings();
    }
    
    @Override
    public void clearWarnings() throws SQLException {
        mStatement.clearWarnings();
    }
    
    @Override
    public void setCursorName(String pName) throws SQLException {
        mStatement.setCursorName(pName);
    }
    
    @Override
    public boolean execute(String pSqlStatement) throws SQLException {
        return mStatement.execute(pSqlStatement);
    }
    
    @Override
    public ResultSet getResultSet() throws SQLException {
        return mStatement.getResultSet();
    }
    
    @Override
    public int getUpdateCount() throws SQLException {
        return mStatement.getUpdateCount();
    }
    
    @Override
    public boolean getMoreResults() throws SQLException {
        return mStatement.getMoreResults();
    }
    
    @Override
    public void setFetchDirection(int pDirection) throws SQLException {
        mStatement.setFetchDirection(pDirection);
    }
    
    @Override
    public int getFetchDirection() throws SQLException {
        return mStatement.getFetchDirection();
    }
    
    @Override
    public void setFetchSize(int pRows) throws SQLException {
        mStatement.setFetchSize(pRows);
    }
    
    @Override
    public int getFetchSize() throws SQLException {
        return mStatement.getFetchSize();
    }

    @Override
    public int getResultSetConcurrency() throws SQLException {
        return mStatement.getResultSetConcurrency();
    }

    @Override
    public int getResultSetType() throws SQLException {
        return mStatement.getResultSetType();
    }

    @Override
    public void addBatch(String pSqlStatement) throws SQLException {
        mStatement.addBatch(pSqlStatement);
    }

    @Override
    public void clearBatch() throws SQLException {
        mStatement.clearBatch();
    }
    
    @Override
    public int[] executeBatch() throws SQLException {
        return mStatement.executeBatch();
    }

    @Override
    public Connection getConnection() throws SQLException {
        return mStatement.getConnection();
    }

    @Override
    public boolean getMoreResults(int pCurrent) throws SQLException {
        return mStatement.getMoreResults(pCurrent);
    }

    @Override
    public ResultSet getGeneratedKeys() throws SQLException {
        return mStatement.getGeneratedKeys();
    }

    @Override
    public int executeUpdate(String pSqlStatement, int pAutoGeneratedKeys) throws SQLException {
        return mStatement.executeUpdate(pSqlStatement, pAutoGeneratedKeys);
    }

    @Override
    public int executeUpdate(String pSqlStatement, int[] pColumnIndexes) throws SQLException {
        return mStatement.executeUpdate(pSqlStatement, pColumnIndexes);
    }

    @Override
    public int executeUpdate(String pSqlStatement, String[] pColumnNames) throws SQLException {
        return mStatement.executeUpdate(pSqlStatement, pColumnNames);
    }

    @Override
    public boolean execute(String pSqlStatement, int pAutoGeneratedKeys) throws SQLException {
        return mStatement.execute(pSqlStatement, pAutoGeneratedKeys);
    }

    @Override
    public boolean execute(String pSqlStatement, int[] pColumnIndexes) throws SQLException {
        return mStatement.execute(pSqlStatement, pColumnIndexes);
    }

    @Override
    public boolean execute(String pSqlStatement, String[] pColumnNames) throws SQLException {
        return mStatement.execute(pSqlStatement, pColumnNames);
    }

    @Override
    public int getResultSetHoldability() throws SQLException {
        return mStatement.getResultSetHoldability();
    }

    @Override
    public boolean isClosed() throws SQLException {
        return mStatement.isClosed();
    }

    @Override
    public void setPoolable(boolean pPoolable) throws SQLException {
        mStatement.setPoolable(pPoolable);
    }

    @Override
    public boolean isPoolable() throws SQLException {
        return mStatement.isPoolable();
    }

    @Override
    public void closeOnCompletion() throws SQLException {
        mStatement.closeOnCompletion();
    }

    @Override
    public boolean isCloseOnCompletion() throws SQLException {
        return mStatement.isCloseOnCompletion();
    }

    @Override
    public <T> T unwrap(Class<T> pIFace) throws SQLException {
        return mStatement.unwrap(pIFace);
    }

    @Override
    public boolean isWrapperFor(Class<?> pIFace) throws SQLException {
        return mStatement.isWrapperFor(pIFace);
    }

    @Override
    public ResultSet executeQuery() throws SQLException {
        return mStatement.executeQuery();
    }

    @Override
    public int executeUpdate() throws SQLException {
        return mStatement.executeUpdate();
    }

    @Override
    public void setNull(String pParameterName, int pSqlType) throws SQLException {
        int[] indexes = getIndexes(pParameterName);
        for (int i = 0; i < indexes.length; i++) {
            mStatement.setNull(indexes[i], pSqlType);
        }
    }

    @Override
    public void setBoolean(String pParameterName, boolean pX) throws SQLException {
        int[] indexes = getIndexes(pParameterName);
        for (int i = 0; i < indexes.length; i++) {
            mStatement.setBoolean(indexes[i], pX);
        }
    }

    @Override
    public void setByte(String pParameterName, byte pX) throws SQLException {
        int[] indexes = getIndexes(pParameterName);
        for (int i = 0; i < indexes.length; i++) {
            mStatement.setByte(indexes[i], pX);
        }
    }

    @Override
    public void setShort(String pParameterName, short pX) throws SQLException {
        int[] indexes = getIndexes(pParameterName);
        for (int i = 0; i < indexes.length; i++) {
            mStatement.setShort(indexes[i], pX);
        }
    }

    @Override
    public void setInt(String pParameterName, int pX) throws SQLException {
        int[] indexes = getIndexes(pParameterName);
        for (int i = 0; i < indexes.length; i++) {
            mStatement.setInt(indexes[i], pX);
        }
    }

    @Override
    public void setLong(String pParameterName, long pX) throws SQLException {
        int[] indexes = getIndexes(pParameterName);
        for (int i = 0; i < indexes.length; i++) {
            mStatement.setLong(indexes[i], pX);
        }
    }

    @Override
    public void setFloat(String pParameterName, float pX) throws SQLException {
        int[] indexes = getIndexes(pParameterName);
        for (int i = 0; i < indexes.length; i++) {
            mStatement.setFloat(indexes[i], pX);
        }
    }

    @Override
    public void setDouble(String pParameterName, double pX) throws SQLException {
        int[] indexes = getIndexes(pParameterName);
        for (int i = 0; i < indexes.length; i++) {
            mStatement.setDouble(indexes[i], pX);
        }
    }

    @Override
    public void setBigDecimal(String pParameterName, BigDecimal pX) throws SQLException {
        int[] indexes = getIndexes(pParameterName);
        for (int i = 0; i < indexes.length; i++) {
            mStatement.setBigDecimal(indexes[i], pX);
        }
    }

    @Override
    public void setString(String parameterName, String pX) throws SQLException {
        int[] indexes = getIndexes(parameterName);
        for (int i = 0; i < indexes.length; i++) {
            mStatement.setString(indexes[i], pX);
        }
    }

    @Override
    public void setBytes(String pParameterName, byte[] pX) throws SQLException {
        int[] indexes = getIndexes(pParameterName);
        for (int i = 0; i < indexes.length; i++) {
            mStatement.setBytes(indexes[i], pX);
        }
    }

    @Override
    public void setDate(String pParameterName, Date pX) throws SQLException {
        int[] indexes = getIndexes(pParameterName);
        for (int i = 0; i < indexes.length; i++) {
            mStatement.setDate(indexes[i], pX);
        }
    }

    @Override
    public void setTime(String pParameterName, Time pX) throws SQLException {
        int[] indexes = getIndexes(pParameterName);
        for (int i = 0; i < indexes.length; i++) {
            mStatement.setTime(indexes[i], pX);
        }
    }

    @Override
    public void setTimestamp(String pParameterName, Timestamp pX) throws SQLException {
        int[] indexes = getIndexes(pParameterName);
        for (int i = 0; i < indexes.length; i++) {
            mStatement.setTimestamp(indexes[i], pX);
        }
    }

    @Override
    public void setAsciiStream(String pParameterName, InputStream pX, int pLength) throws SQLException {
        int[] indexes = getIndexes(pParameterName);
        for (int i = 0; i < indexes.length; i++) {
            mStatement.setAsciiStream(indexes[i], pX, pLength);
        }
    }

    @Override
    public void setBinaryStream(String pParameterName, InputStream pX, int pLength) throws SQLException {
        int[] indexes = getIndexes(pParameterName);
        for (int i = 0; i < indexes.length; i++) {
            mStatement.setBinaryStream(indexes[i], pX, pLength);
        }
    }

    @Override
    public void clearParameters() throws SQLException {
        mStatement.clearParameters();
    }

    @Override
    public void setObject(String pParameterName, Object pX, int pTargetSqlType) throws SQLException {
        int[] indexes = getIndexes(pParameterName);
        for (int i = 0; i < indexes.length; i++) {
            mStatement.setObject(indexes[i], pX, pTargetSqlType);
        }
    }

    @Override
    public void setObject(String pParameterName, Object pX) throws SQLException {
        int[] indexes = getIndexes(pParameterName);
        for (int i = 0; i < indexes.length; i++) {
            mStatement.setObject(indexes[i], pX);
        }
    }

    @Override
    public boolean execute() throws SQLException {
        return mStatement.execute();
    }

    @Override
    public void addBatch() throws SQLException {
        mStatement.addBatch();
    }

    @Override
    public void setCharacterStream(String pParameterName, Reader pReader, int pLength) throws SQLException {
        int[] indexes = getIndexes(pParameterName);
        for (int i = 0; i < indexes.length; i++) {
            mStatement.setCharacterStream(indexes[i], pReader, pLength);
        }
    }

    @Override
    public void setBlob(String pParameterName, Blob pX) throws SQLException {
        int[] indexes = getIndexes(pParameterName);
        for (int i = 0; i < indexes.length; i++) {
            mStatement.setBlob(indexes[i], pX);
        }
    }

    @Override
    public void setClob(String pParameterName, Clob pX) throws SQLException {
        int[] indexes = getIndexes(pParameterName);
        for (int i = 0; i < indexes.length; i++) {
            mStatement.setClob(indexes[i], pX);
        }
    }

    @Override
    public ResultSetMetaData getMetaData() throws SQLException {
        return mStatement.getMetaData();
    }

    @Override
    public void setDate(String pParameterName, Date pX, Calendar pCalendar) throws SQLException {
        int[] indexes = getIndexes(pParameterName);
        for (int i = 0; i < indexes.length; i++) {
            mStatement.setDate(indexes[i], pX, pCalendar);
        }
    }

    @Override
    public void setTime(String pParameterName, Time pX, Calendar pCalendar) throws SQLException {
        int[] indexes = getIndexes(pParameterName);
        for (int i = 0; i < indexes.length; i++) {
            mStatement.setTime(indexes[i], pX, pCalendar);
        }
    }

    @Override
    public void setTimestamp(String pParameterName, Timestamp pX, Calendar pCalendar) throws SQLException {
        int[] indexes = getIndexes(pParameterName);
        for (int i = 0; i < indexes.length; i++) {
            mStatement.setTimestamp(indexes[i], pX, pCalendar);
        }
    }

    @Override
    public void setNull(String pParameterName, int sqlType, String pTypeName) throws SQLException {
        int[] indexes = getIndexes(pParameterName);
        for (int i = 0; i < indexes.length; i++) {
            mStatement.setNull(indexes[i], sqlType, pTypeName);
        }
    }

    @Override
    public void setURL(String pParameterName, URL pX) throws SQLException {
        int[] indexes = getIndexes(pParameterName);
        for (int i = 0; i < indexes.length; i++) {
            mStatement.setURL(indexes[i], pX);
        }
    }

    @Override
    public ParameterMetaData getParameterMetaData() throws SQLException {
        return mStatement.getParameterMetaData();
    }

    @Override
    public void setRowId(String pParameterName, RowId pX) throws SQLException {
        int[] indexes = getIndexes(pParameterName);
        for (int i = 0; i < indexes.length; i++) {
            mStatement.setRowId(indexes[i], pX);
        }
    }

    @Override
    public void setNString(String pParameterName, String value) throws SQLException {
        int[] indexes = getIndexes(pParameterName);
        for (int i = 0; i < indexes.length; i++) {
            mStatement.setNString(indexes[i], value);
        }
    }

    @Override
    public void setNCharacterStream(String pParameterName, Reader pValue, long pLength) throws SQLException {
        int[] indexes = getIndexes(pParameterName);
        for (int i = 0; i < indexes.length; i++) {
            mStatement.setNCharacterStream(indexes[i], pValue, pLength);
        }
    }

    @Override
    public void setNClob(String pParameterName, NClob pValue) throws SQLException {
        int[] indexes = getIndexes(pParameterName);
        for (int i = 0; i < indexes.length; i++) {
            mStatement.setNClob(indexes[i], pValue);
        }
    }

    @Override
    public void setClob(String pParameterName, Reader pReader, long pLength) throws SQLException {
        int[] indexes = getIndexes(pParameterName);
        for (int i = 0; i < indexes.length; i++) {
            mStatement.setClob(indexes[i], pReader, pLength);
        }
    }

    @Override
    public void setBlob(String pParameterName, InputStream pInputStream, long pLength) throws SQLException {
        int[] indexes = getIndexes(pParameterName);
        for (int i = 0; i < indexes.length; i++) {
            mStatement.setBlob(indexes[i], pInputStream, pLength);
        }
    }

    @Override
    public void setNClob(String pParameterName, Reader pReader, long pLength) throws SQLException {
        int[] indexes = getIndexes(pParameterName);
        for (int i = 0; i < indexes.length; i++) {
            mStatement.setNClob(indexes[i], pReader, pLength);
        }
    }

    @Override
    public void setSQLXML(String pParameterName, SQLXML pXmlObject) throws SQLException {
        int[] indexes = getIndexes(pParameterName);
        for (int i = 0; i < indexes.length; i++) {
            mStatement.setSQLXML(indexes[i], pXmlObject);
        }
    }

    @Override
    public void setObject(String pParameterName, Object pX, int pTargetSqlType, int pScaleOrLength) throws SQLException {
        int[] indexes = getIndexes(pParameterName);
        for (int i = 0; i < indexes.length; i++) {
            mStatement.setObject(indexes[i], pX, pTargetSqlType, pScaleOrLength);
        }
    }

    @Override
    public void setAsciiStream(String pParameterName, InputStream pX, long pLength) throws SQLException {
        int[] indexes = getIndexes(pParameterName);
        for (int i = 0; i < indexes.length; i++) {
            mStatement.setAsciiStream(indexes[i], pX, pLength);
        }
    }

    @Override
    public void setBinaryStream(String pParameterName, InputStream pX, long pLength) throws SQLException {
        int[] indexes = getIndexes(pParameterName);
        for (int i = 0; i < indexes.length; i++) {
            mStatement.setBinaryStream(indexes[i], pX, pLength);
        }
    }

    @Override
    public void setCharacterStream(String pParameterName, Reader pReader, long pLength) throws SQLException {
        int[] indexes = getIndexes(pParameterName);
        for (int i = 0; i < indexes.length; i++) {
            mStatement.setCharacterStream(indexes[i], pReader, pLength);
        }
    }

    @Override
    public void setAsciiStream(String pParameterName, InputStream pX) throws SQLException {
        int[] indexes = getIndexes(pParameterName);
        for (int i = 0; i < indexes.length; i++) {
            mStatement.setAsciiStream(indexes[i], pX);
        }
    }

    @Override
    public void setBinaryStream(String pParameterName, InputStream pX) throws SQLException {
        int[] indexes = getIndexes(pParameterName);
        for (int i = 0; i < indexes.length; i++) {
            mStatement.setBinaryStream(indexes[i], pX);
        }
    }

    @Override
    public void setCharacterStream(String pParameterName, Reader pReader) throws SQLException {
        int[] indexes = getIndexes(pParameterName);
        for (int i = 0; i < indexes.length; i++) {
            mStatement.setCharacterStream(indexes[i], pReader);
        }
    }

    @Override
    public void setNCharacterStream(String pParameterName, Reader pValue) throws SQLException {
        int[] indexes = getIndexes(pParameterName);
        for (int i = 0; i < indexes.length; i++) {
            mStatement.setNCharacterStream(indexes[i], pValue);
        }
    }

    @Override
    public void setClob(String pParameterName, Reader pReader) throws SQLException {
        int[] indexes = getIndexes(pParameterName);
        for (int i = 0; i < indexes.length; i++) {
            mStatement.setClob(indexes[i], pReader);
        }
    }

    @Override
    public void setBlob(String pParameterName, InputStream pInputStream) throws SQLException {
        int[] indexes = getIndexes(pParameterName);
        for (int i = 0; i < indexes.length; i++) {
            mStatement.setBlob(indexes[i], pInputStream);
        }
    }

    @Override
    public void setNClob(String pParameterName, Reader pReader) throws SQLException {
        int[] indexes = getIndexes(pParameterName);
        for (int i = 0; i < indexes.length; i++) {
            mStatement.setNClob(indexes[i], pReader);
        }
    }

    @Override
    public void setNull(int pParameterIndex, int pSqlType) throws SQLException {
        mStatement.setNull(pParameterIndex, pSqlType);
    }

    @Override
    public void setBoolean(int pParameterIndex, boolean pX) throws SQLException {
        mStatement.setBoolean(pParameterIndex, pX);
    }

    @Override
    public void setByte(int pParameterIndex, byte pX) throws SQLException {
        mStatement.setByte(pParameterIndex, pX);
    }

    @Override
    public void setShort(int pParameterIndex, short pX) throws SQLException {
        mStatement.setShort(pParameterIndex, pX);
    }

    @Override
    public void setInt(int pParameterIndex, int pX) throws SQLException {
        mStatement.setInt(pParameterIndex, pX);
    }

    @Override
    public void setLong(int pParameterIndex, long pX) throws SQLException {
        mStatement.setLong(pParameterIndex, pX);
    }

    @Override
    public void setFloat(int pParameterIndex, float pX) throws SQLException {
        mStatement.setFloat(pParameterIndex, pX);
    }

    @Override
    public void setDouble(int pParameterIndex, double pX) throws SQLException {
        mStatement.setDouble(pParameterIndex, pX);
    }

    @Override
    public void setBigDecimal(int pParameterIndex, BigDecimal pX) throws SQLException {
        mStatement.setBigDecimal(pParameterIndex, pX);
    }

    @Override
    public void setString(int pParameterIndex, String pX) throws SQLException {
        mStatement.setString(pParameterIndex, pX);
    }

    @Override
    public void setBytes(int pParameterIndex, byte[] pX) throws SQLException {
        mStatement.setBytes(pParameterIndex, pX);
    }

    @Override
    public void setDate(int pParameterIndex, Date pX) throws SQLException {
        mStatement.setDate(pParameterIndex, pX);
    }

    @Override
    public void setTime(int pParameterIndex, Time pX) throws SQLException {
        mStatement.setTime(pParameterIndex, pX);
    }

    @Override
    public void setTimestamp(int pParameterIndex, Timestamp pX) throws SQLException {
        mStatement.setTimestamp(pParameterIndex, pX);
    }

    @Override
    public void setAsciiStream(int pParameterIndex, InputStream pX, int pLength) throws SQLException {
        mStatement.setAsciiStream(pParameterIndex, pX, pLength);
    }

    @Override
    public void setUnicodeStream(int pParameterIndex, InputStream pX, int pLength) throws SQLException {
        mStatement.setUnicodeStream(pParameterIndex, pX, pLength);
    }

    @Override
    public void setBinaryStream(int pParameterIndex, InputStream pX, int pLength) throws SQLException {
        mStatement.setBinaryStream(pParameterIndex, pX, pLength);
    }

    @Override
    public void setObject(int pParameterIndex, Object pX, int pTargetSqlType) throws SQLException {
        mStatement.setObject(pParameterIndex, pX, pTargetSqlType);
    }

    @Override
    public void setObject(int pParameterIndex, Object pX) throws SQLException {
        mStatement.setObject(pParameterIndex, pX);
    }

    @Override
    public void setCharacterStream(int pParameterIndex, Reader pReader, int pLength) throws SQLException {
        mStatement.setCharacterStream(pParameterIndex, pReader, pLength);
    }

    @Override
    public void setRef(int pParameterIndex, Ref pX) throws SQLException {
        mStatement.setRef(pParameterIndex, pX);
    }

    @Override
    public void setBlob(int pParameterIndex, Blob pX) throws SQLException {
        mStatement.setBlob(pParameterIndex, pX);
    }

    @Override
    public void setClob(int pParameterIndex, Clob pX) throws SQLException {
        mStatement.setClob(pParameterIndex, pX);
    }

    @Override
    public void setArray(int pParameterIndex, Array pX) throws SQLException {
        mStatement.setArray(pParameterIndex, pX);
    }

    @Override
    public void setDate(int pParameterIndex, Date pX, Calendar pCalendar) throws SQLException {
        mStatement.setDate(pParameterIndex, pX, pCalendar);
    }

    @Override
    public void setTime(int pParameterIndex, Time pX, Calendar pCalendar) throws SQLException {
        mStatement.setTime(pParameterIndex, pX, pCalendar);
    }

    @Override
    public void setTimestamp(int pParameterIndex, Timestamp pX, Calendar pCalendar) throws SQLException {
        mStatement.setTimestamp(pParameterIndex, pX, pCalendar);
    }

    @Override
    public void setNull(int pParameterIndex, int pSqlType, String pTypeName) throws SQLException {
        mStatement.setNull(pParameterIndex, pSqlType, pTypeName);
    }

    @Override
    public void setURL(int pParameterIndex, URL pX) throws SQLException {
        mStatement.setURL(pParameterIndex, pX);
    }

    @Override
    public void setRowId(int pParameterIndex, RowId pX) throws SQLException {
        mStatement.setRowId(pParameterIndex, pX);
    }

    @Override
    public void setNString(int pParameterIndex, String pValue) throws SQLException {
        mStatement.setNString(pParameterIndex, pValue);
    }

    @Override
    public void setNCharacterStream(int pParameterIndex, Reader pValue, long pLength) throws SQLException {
        mStatement.setNCharacterStream(pParameterIndex, pValue, pLength);
    }

    @Override
    public void setNClob(int pParameterIndex, NClob pValue) throws SQLException {
        mStatement.setNClob(pParameterIndex, pValue);
    }

    @Override
    public void setClob(int pParameterIndex, Reader pReader, long pLength) throws SQLException {
        mStatement.setClob(pParameterIndex, pReader, pLength);
    }

    @Override
    public void setBlob(int pParameterIndex, InputStream pInputStream, long pLength) throws SQLException {
        mStatement.setBlob(pParameterIndex, pInputStream, pLength);
    }

    @Override
    public void setNClob(int pParameterIndex, Reader pReader, long pLength) throws SQLException {
        mStatement.setNClob(pParameterIndex, pReader, pLength);
    }

    @Override
    public void setSQLXML(int pParameterIndex, SQLXML pXmlObject) throws SQLException {
        mStatement.setSQLXML(pParameterIndex, pXmlObject);
    }

    @Override
    public void setObject(int pParameterIndex, Object pX, int pTargetSqlType, int pScaleOrLength) throws SQLException {
        mStatement.setObject(pParameterIndex, pX, pTargetSqlType, pScaleOrLength);
    }

    @Override
    public void setAsciiStream(int pParameterIndex, InputStream pX, long pLength) throws SQLException {
        mStatement.setAsciiStream(pParameterIndex, pX, pLength);
    }

    @Override
    public void setBinaryStream(int pParameterIndex, InputStream pX, long pLength) throws SQLException {
        mStatement.setBinaryStream(pParameterIndex, pX, pLength);
    }

    @Override
    public void setCharacterStream(int pParameterIndex, Reader pReader, long pLength) throws SQLException {
        mStatement.setCharacterStream(pParameterIndex, pReader, pLength);
    }

    @Override
    public void setAsciiStream(int pParameterIndex, InputStream pX) throws SQLException {
        mStatement.setAsciiStream(pParameterIndex, pX);
    }

    @Override
    public void setBinaryStream(int pParameterIndex, InputStream pX) throws SQLException {
        mStatement.setBinaryStream(pParameterIndex, pX);
    }

    @Override
    public void setCharacterStream(int pParameterIndex, Reader pReader) throws SQLException {
        mStatement.setCharacterStream(pParameterIndex, pReader);
    }

    @Override
    public void setNCharacterStream(int pParameterIndex, Reader pValue) throws SQLException {
        mStatement.setNCharacterStream(pParameterIndex, pValue);
    }

    @Override
    public void setClob(int pParameterIndex, Reader pReader) throws SQLException {
        mStatement.setClob(pParameterIndex, pReader);
    }

    @Override
    public void setBlob(int pParameterIndex, InputStream pInputStream) throws SQLException {
        mStatement.setBlob(pParameterIndex, pInputStream);
    }

    @Override
    public void setNClob(int pParameterIndex, Reader pReader) throws SQLException {
        mStatement.setNClob(pParameterIndex, pReader);
    }
    
    // <editor-fold defaultstate="collapsed" desc="Unsupported methods">
    @Override
    public void registerOutParameter(int pParameterIndex, int pSqlType) throws SQLException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public void registerOutParameter(int pParameterIndex, int pSqlType, int pScale) throws SQLException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public boolean wasNull() throws SQLException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public String getString(int pParameterIndex) throws SQLException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public boolean getBoolean(int pParameterIndex) throws SQLException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public byte getByte(int pParameterIndex) throws SQLException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public short getShort(int pParameterIndex) throws SQLException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public int getInt(int pParameterIndex) throws SQLException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public long getLong(int pParameterIndex) throws SQLException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public float getFloat(int pParameterIndex) throws SQLException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public double getDouble(int pParameterIndex) throws SQLException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public BigDecimal getBigDecimal(int pParameterIndex, int pScale) throws SQLException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public byte[] getBytes(int pParameterIndex) throws SQLException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public Date getDate(int pParameterIndex) throws SQLException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public Time getTime(int pParameterIndex) throws SQLException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public Timestamp getTimestamp(int pParameterIndex) throws SQLException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public Object getObject(int pParameterIndex) throws SQLException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public BigDecimal getBigDecimal(int pParameterIndex) throws SQLException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public Object getObject(int pParameterIndex, Map<String, Class<?>> pMap) throws SQLException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public Ref getRef(int pParameterIndex) throws SQLException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public Blob getBlob(int pParameterIndex) throws SQLException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public Clob getClob(int pParameterIndex) throws SQLException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public Array getArray(int pParameterIndex) throws SQLException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public Date getDate(int pParameterIndex, Calendar pCalendar) throws SQLException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public Time getTime(int pParameterIndex, Calendar pCalendar) throws SQLException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public Timestamp getTimestamp(int pParameterIndex, Calendar pCalendar) throws SQLException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public void registerOutParameter(int pParameterIndex, int pSqlType, String pTypeName) throws SQLException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public void registerOutParameter(String pParameterName, int pSqlType) throws SQLException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public void registerOutParameter(String pParameterName, int pSqlType, int pScale) throws SQLException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public void registerOutParameter(String pParameterName, int pSqlType, String pTypeName) throws SQLException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public URL getURL(int pParameterIndex) throws SQLException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public String getString(String pParameterName) throws SQLException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public boolean getBoolean(String pParameterName) throws SQLException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public byte getByte(String pParameterName) throws SQLException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public short getShort(String pParameterName) throws SQLException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public int getInt(String pParameterName) throws SQLException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public long getLong(String pParameterName) throws SQLException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public float getFloat(String pParameterName) throws SQLException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public double getDouble(String pParameterName) throws SQLException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public byte[] getBytes(String pParameterName) throws SQLException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public Date getDate(String pParameterName) throws SQLException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public Time getTime(String pParameterName) throws SQLException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public Timestamp getTimestamp(String pParameterName) throws SQLException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public Object getObject(String pParameterName) throws SQLException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public BigDecimal getBigDecimal(String pParameterName) throws SQLException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public Object getObject(String pParameterName, Map<String, Class<?>> pMap) throws SQLException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public Ref getRef(String pParameterName) throws SQLException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public Blob getBlob(String pParameterName) throws SQLException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public Clob getClob(String pParameterName) throws SQLException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public Array getArray(String pParameterName) throws SQLException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public Date getDate(String pParameterName, Calendar pCalendar) throws SQLException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public Time getTime(String pParameterName, Calendar pCalendar) throws SQLException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public Timestamp getTimestamp(String pParameterName, Calendar pCalendar) throws SQLException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public URL getURL(String pParameterName) throws SQLException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public RowId getRowId(int pParameterIndex) throws SQLException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public RowId getRowId(String pParameterName) throws SQLException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public NClob getNClob(int pParameterIndex) throws SQLException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public NClob getNClob(String pParameterName) throws SQLException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public SQLXML getSQLXML(int pParameterIndex) throws SQLException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public SQLXML getSQLXML(String pParameterName) throws SQLException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public String getNString(int pParameterIndex) throws SQLException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public String getNString(String pParameterName) throws SQLException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public Reader getNCharacterStream(int pParameterIndex) throws SQLException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public Reader getNCharacterStream(String pParameterName) throws SQLException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public Reader getCharacterStream(int pParameterIndex) throws SQLException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public Reader getCharacterStream(String pParameterName) throws SQLException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public <T> T getObject(int pParameterIndex, Class<T> pType) throws SQLException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public <T> T getObject(String pParameterName, Class<T> pType) throws SQLException {
        throw new UnsupportedOperationException("Not supported yet.");
    }
    
    // </editor-fold>
    
    public void setUnicodeStream(String pParameterName, InputStream pX, int pLength) throws SQLException {
        int[] indexes = getIndexes(pParameterName);
        for (int i = 0; i < indexes.length; i++) {
            mStatement.setUnicodeStream(indexes[i], pX, pLength);
        }
    }
    
    public void setRef(String pParameterName, Ref pX) throws SQLException {
        int[] indexes = getIndexes(pParameterName);
        for (int i = 0; i < indexes.length; i++) {
            mStatement.setRef(indexes[i], pX);
        }
    }
    
    public void setArray(String pParameterName, Array pX) throws SQLException {
        int[] indexes = getIndexes(pParameterName);
        for (int i = 0; i < indexes.length; i++) {
            mStatement.setArray(indexes[i], pX);
        }
    }
}
